<template>
    <div :class="[fixed ? 'fixTable' : '', 'tableClass']">
        <a-table
            :columns="columns"
            :loading="loading"
            :rowSelection="rowSelection"
            :rowKey="rowKey"
            size="small"
            :data-source="data"
            :pagination="pageOptions"
            :bordered="true"
            :customRow="customRow"
            :scroll="{ x: scrollX, y: scrollY }"
            v-bind="{ ...$props, ...$attrs }"
            @change="paginationChange"
        >
            <!-- 自定义渲染[比如字段转换啥的。。-->
            <template
                v-for="slotItem in columns.filter((item) => item.slots)"
                :key="slotItem.dataIndex || slotItem.slots.customRender"
                #[slotItem.slots.customRender]="slotProps"
            >
                <slot v-if="$slots[slotItem.slots.customRender]" :name="slotItem.slots.customRender" v-bind="slotProps"></slot>
            </template>
        </a-table>
    </div>
</template>

<script lang="ts">
import { defineComponent, reactive, PropType, toRefs, watch } from 'vue'
import { Card, Select, Table, Popconfirm } from 'ant-design-vue'
import { TableProps } from 'ant-design-vue/lib/table/interface'
import { usePagination, PageOption } from '@/hooks/usePagination'
import { useDragRow, useDragCol } from './hooks'
import { Columns } from './types'
import { useStore } from '@/store'
export default defineComponent({
    name: 'DynamicTable',
    components: {
        [Table.name]: Table,
        [Card.name]: Card,
        [Select.name]: Select,
        [Popconfirm.name]: Popconfirm,
        Option: Select.Option
    },
    inheritAttrs: false,
    props: {
        tableType: Number,
        columns: {
            type: Object as PropType<Columns[]>,
            required: true
        },
        getListFunc: {
            // 获取列表数据函数API
            type: Function,
            required: true
        },
        rowSelection: {
            type: Object
        },
        rowKey: {
            // 表格唯一字段
            type: [String, Function] as PropType<string | ((record: any) => string)>
        },
        pageOption: {
            // 分页参数
            type: Object as PropType<PageOption>,
            default: () => ({})
        },
        queryParam: {
            type: Object,
            default: () => ({})
        },
        dragColEnable: {
            type: Boolean as PropType<boolean>,
            default: false
        },
        fixed: {
            type: Boolean as PropType<boolean>,
            default: false
        },
        initData: {
            type: Boolean as PropType<boolean>,
            default: true
        },
        scrollX: {
            type: Number as PropType<number>,
            default: 0
        },
        dragRowEnable: Boolean as PropType<boolean>
    },
    emits: ['change'],
    setup(props, { emit }) {
        const { pageOptions } = usePagination()
        const store = useStore()
        Object.assign(pageOptions.value, props.pageOption)

        // 开启表格伸缩列
        props.dragColEnable && useDragCol(props.columns)

        const state = reactive({
            queryParam: props.queryParam,
            expandItemRefs: {},
            customRow: () => ({} as TableProps['customRow']),
            data: [], // 表格数据
            actions: props.columns.find((item) => (item.dataIndex || item.key) == 'action')?.actions || [], // 表格操作（如：编辑、删除的按钮等）
            loading: false, // 表格加载
            scrollY: 0 as number | string,
            pageSizeTemp: 10
        })
        //重置分页
        const resetPagination = () => {
            pageOptions.value.current = 1
            pageOptions.value.pageSize = 10
        }
        // 获取表格数据
        const refreshTableData = async (v = '') => {
            if (props.tableType == 1) {
                var params = {
                    pageNo: pageOptions.value.current,
                    pageSize: pageOptions.value.pageSize,
                    ...props.pageOption,
                    ...state.queryParam
                } as any
            } else {
                params = {
                    current: pageOptions.value.current,
                    size: pageOptions.value.pageSize,
                    ...props.pageOption,
                    ...state.queryParam
                }
            }
            state.loading = true
            const data = await props.getListFunc(params).finally(() => (state.loading = false))
            Object.assign(pageOptions.value, {
                current: ~~(props.tableType == 1 ? data.pageNo : data.current),
                pageSize: ~~(props.tableType == 1 ? data.pageSize : data.size),
                total: ~~(props.tableType == 1 ? data.totalRows : data.total)
            })
            state.data = props.tableType == 1 ? data.rows : data.records
            if (v && state.data.length == 0) {
                resetPagination()
                refreshTableData()
            }
            // 是否可以拖拽行
            props.dragRowEnable && (state.customRow = useDragRow<any>(state.data)!)
        }
        props.fixed && (state.scrollY = 'calc(100vh - 290px)')
        props.initData && refreshTableData()

        // 操作事件
        const actionEvent = async (record, func, actionType) => {
            // 将refreshTableData放入宏任务中,等待当前微任务拿到结果进行判断操作，再请求表格数据
            await func({ record, props }, () => setTimeout(() => refreshTableData()))
            // 如果为删除操作,并且删除成功，当前的表格数据条数小于2条,则当前页数减一,即请求前一页
            if (actionType == 'del' && state.data.length < 2) {
                pageOptions.value.current = Math.max(1, pageOptions.value.current - 1)
            }
        }

        // 分页改变
        const paginationChange = (pagination, filters, sorter, { currentDataSource }) => {
            const { field, order } = sorter
            pageOptions.value = {
                ...pageOptions.value,
                ...pagination
            }
            if (props.tableType == 1) {
                var currentOptions = {
                    pageNo: pagination.current,
                    pageSize: pagination.pageSize,
                    ...props.pageOption,
                    ...filters,
                    field,
                    order
                }
            } else {
                var currentOptions = {
                    current: pageOptions.value.current,
                    size: pageOptions.value.pageSize,
                    ...props.pageOption,
                    ...filters,
                    field,
                    order
                }
            }
            // 暂时不封装排序，筛选等
            refreshTableData('repeat')
            emit('change', currentOptions, filters, sorter, { currentDataSource })
            state.pageSizeTemp = pagination.pageSize
        }
        watch(
            () => state.pageSizeTemp,
            (v, ov) => {
                const container = document.querySelector('.ant-layout-content.ps')
                if (container && container !== null && container.scrollTop && v < ov && !props.fixed) {
                    container.scrollTop = 0
                }
            }
        )
        watch(
            () => pageOptions.value.current,
            (v, ov) => {
                const container = document.querySelector('.ant-layout-content.ps')
                if (
                    container &&
                    container !== null &&
                    container.scrollTop &&
                    !props.fixed &&
                    v == Math.ceil(pageOptions.value.total / pageOptions.value.pageSize)
                ) {
                    container.scrollTop = 0
                }
            }
        )
        watch(
            [() => store.state.app.showBread, () => store.state.app.multiTab],
            ([sv], [mv]) => {
                const ht = 254
                const h1 = store.state.app.showBread ? 36 : 0
                const h2 = store.state.app.multiTab ? 40 : 0
                if (props.fixed) {
                    state.scrollY = `calc(100vh - ${ht + h1 + h2}px)`
                }
            },
            {
                immediate: true
            }
        )

        // dataIndex 可以为 a.b.c
        // const getDataIndexVal = (dataIndex, record) => dataIndex.split('.').reduce((pre, curr) => pre[curr], record)

        const buttonProps = {
            size: 'small'
        }

        return {
            ...toRefs(state),
            pageOptions,
            buttonProps,
            actionEvent,
            refreshTableData,
            resetPagination,
            paginationChange
        }
    }
})
</script>

<style lang="scss" scoped>
::v-deep(.ant-pagination) {
    padding: 0 8px 0 0;
}
::v-deep(.ant-table .ant-table-title) {
    display: flex;

    .ant-btn {
        margin-right: 10px;
    }
}

.actions > * {
    margin-right: 10px;
}
::v-deep(.ant-table-pagination.ant-pagination) {
    margin: 10px 0 !important;
}
// ::v-deep(.ant-spin-nested-loading) {
//     flex: 1;
// }
.tableClass {
    background: #fff;
    padding: 0 10px;
}
.fixTable {
    // flex: 1;
    padding-bottom: 0;
}
</style>
